/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2011.09.18                                          *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_bdry_InitializationCondition_h
#define FreeMAPs_include_COMMON_bdry_InitializationCondition_h

#include "FreeMAPsConfig.h"

//LIBMESH headers

//COMMON headers
#include "COMMON/base/Common.h"
#include "COMMON/base/StateIndicator.h"
#include "COMMON/enum/VariableType.h"


namespace FreeMAPs
{

//forward declarations
class PDEEquationEnsembleStrategy;
class Point;


/**
 * this class do the initialize of a simulation ensemble.
 * and actually it some times do initialize not only on the
 * start of simulation, but last for a time.
 * @see BoundaryCondition.
 */
class InitializationCondition : public StateIndicator
{
public:

    explicit
    InitializationCondition (
        const std::string& parent_name,
        const std::string& ic_name);

    virtual
    ~InitializationCondition();

public:

    inline const std::string&
    get_variable_complete_symbol() const;

    /**
     * @return the initialization condition name.
     */
    inline const std::string&
    get_ic_name() const;

//    inline const Function* get_function()const;
    /**
     * @return true if initialization is required
     * @note that if initial_time is true or time is between
     * d_start_time and d_end_time, return true.
     * else return false
     */
    inline bool
    require_initialization (
        const double time,
        const bool initial_time) const;

    inline void
    set_init_value(const double init_value);

    inline double
    get_init_value() const;


public:

    void
    clear();

    /**
     * get information from input database
     */
    void
    get_from_input (
        const InputDatabase* db,
        const PDEEquationEnsembleStrategy& equation_ensemble);

    friend std::ostream&
    operator << (
        std::ostream& os,
        const InitializationCondition& rhs);

private:

    /*
     * return true if it works only on some level set
     */
    inline bool
    is_level_set_considered() const;

private:

    typedef StateIndicator Parent;

    /*
     * the var that this condition act on
     */
    std::string d_variable_complete_symbol;

    /*
     * act on some level set's inside.
     */
    std::set<std::string> d_inside_level_sets;

    /*
     * act on some level set's outside
     * note that if d_inside_level_sets or d_outside_level_sets
     * is not empty, then only those level set will be initialized.
     * if both them are empty, then all level set will be initialized.
     */
    std::set<std::string> d_outside_level_sets;

    /*
     * if true, then set all cells that not initialize to
     * a give value
     */
    bool d_is_value_out_of_range_set;
    double d_value_out_of_range;

    /*
     * usually init conditions only act on start of the simulation.
     * but some time, one want to make it take effect for a time.
     */
    bool d_only_act_on_init;
    double d_start_time;
    double d_end_time;

//    Function* d_init_value;
    double d_init_value;

private:

    DISALLOW_COPY_AND_ASSIGN (InitializationCondition);
};

}

#include "COMMON/bdry/InitializationCondition.inl"

#endif
